/******************************************************************************
 *
 * MotionViewer
 * Copyright (C) 2007 Sangyoon Lee, Electronic Visualization Laboratory, 
 * University of Illinois at Chicago
 *
 * This software is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either Version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
 * License for more details.
 * 
 * You should have received a copy of the GNU Lesser Public License along
 * with this software; if not, write to the Free Software Foundation, Inc., 
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Questions or comments about MotionViewer should be directed to 
 * cavern@evl.uic.edu
 *
 *****************************************************************************/

//-----------------------------------------------------------------------------
//	ClientCodes
//-----------------------------------------------------------------------------
#ifndef __CLIENTCODES_H__
#define __CLIENTCODES_H__

#pragma once
#include <ogreplatform.h>
#include <string>
#include <vector>
#include <functional>
#include "assert.h"

class ClientCodes
{
public:
	enum EType		
	{
		ERequest, 
		EReply
	};

	enum EPacket	
	{
		EClose, 
		EInfo, 
		EData, 
		EStreamOn, 
		EStreamOff
	};

	static const std::vector< std::string > MarkerTokens;
	static const std::vector< std::string > BodyTokens;

	static std::vector< std::string > MakeMarkerTokens()
	{
		std::vector< std::string > v;
		v.push_back("<P-X>");
		v.push_back("<P-Y>");
		v.push_back("<P-Z>");
		v.push_back("<P-O>");
		return v;
	}

	static std::vector< std::string > MakeBodyTokens()
	{
		std::vector< std::string > v;
		v.push_back("<A-X>");
		v.push_back("<A-Y>");
		v.push_back("<A-Z>");
		v.push_back("<T-X>");
		v.push_back("<T-Y>");
		v.push_back("<T-Z>");
		v.push_back("<a-X>");
		v.push_back("<a-Y>");
		v.push_back("<a-Z>");
		v.push_back("<t-X>");
		v.push_back("<t-Y>");
		v.push_back("<t-Z>");
		v.push_back("<ba-X>");
		v.push_back("<ba-Y>");
		v.push_back("<ba-Z>");
		v.push_back("<bt-X>");
		v.push_back("<bt-Y>");
		v.push_back("<bt-Z>");
		return v;
	}

	struct CompareNames : std::binary_function<std::string, std::string, bool>
	{
		bool operator()(const std::string & a_S1, const std::string & a_S2) const
		{
			std::string::const_iterator iS1 = a_S1.begin();
			std::string::const_iterator iS2 = a_S2.begin();

			while(iS1 != a_S1.end() && iS2 != a_S2.end())
				if(toupper(*(iS1++)) != toupper(*(iS2++))) return false;

			return a_S1.size() == a_S2.size();
		}
	};



};

class MarkerChannel
{
public:
	std::string Name;

	int X;
	int Y;
	int Z;
	int O;

	MarkerChannel(std::string & a_rName) : X(-1), Y(-1), Z(-1), O(-1), Name(a_rName) {}

	int & operator[](int i)
	{
		switch(i)
		{
		case 0:		return X;
		case 1:		return Y;
		case 2:		return Z;
		case 3:		return O;
		default:	assert(false); return O;
		}
	}

	int operator[](int i) const
	{
		switch(i)
		{
		case 0:		return X;
		case 1:		return Y;
		case 2:		return Z;
		case 3:		return O;
		default:	assert(false); return -1;
		}
	}


	bool operator==(const std::string & a_rName) 
	{
		ClientCodes::CompareNames comparitor;
		return comparitor(Name, a_rName);
	}

};

struct MarkerData
{
	double X;
	double Y;
	double Z;
	bool   Visible;
};

class BodyChannel
{
public:
	std::string Name;

	int TX;
	int TY;
	int TZ;
	int RX;
	int RY;
	int RZ;
	int tX;
	int tY;
	int tZ;
	int rX;
	int rY;
	int rZ;
	int btX;
	int btY;
	int btZ;
	int baX;
	int baY;
	int baZ;

	BodyChannel(std::string & a_rName) : RX(-1), RY(-1), RZ(-1), TX(-1), TY(-1), TZ(-1), 
										 rX(-1), rY(-1), rZ(-1), tX(-1), tY(-1), tZ(-1),
										 btX(-1), btY(-1), btZ(-1), baX(-1), baY(-1), baZ(-1), Name(a_rName) {}

	int & operator[](int i)
	{
		switch(i)
		{
		case 0:		return RX;
		case 1:		return RY;
		case 2:		return RZ;
		case 3:		return TX;
		case 4:		return TY;
		case 5:		return TZ;
		case 6:		return rX;
		case 7:		return rY;
		case 8:		return rZ;
		case 9:		return tX;
		case 10:	return tY;
		case 11:	return tZ;
		case 12:	return btX;
		case 13:	return btY;
		case 14:	return btZ;
		case 15:	return baX;
		case 16:	return baY;
		case 17:	return baZ;
		default:	assert(false); return TZ;
		}
	}

	int operator[](int i) const
	{
		switch(i)
		{
		case 0:		return RX;
		case 1:		return RY;
		case 2:		return RZ;
		case 3:		return TX;
		case 4:		return TY;
		case 5:		return TZ;
		case 6:		return rX;
		case 7:		return rY;
		case 8:		return rZ;
		case 9:		return tX;
		case 10:	return tY;
		case 11:	return tZ;
		case 12:	return btX;
		case 13:	return btY;
		case 14:	return btZ;
		case 15:	return baX;
		case 16:	return baY;
		case 17:	return baZ;
		default:	assert(false); return -1;
		}
	}

	bool operator==(const std::string & a_rName) 
	{
		ClientCodes::CompareNames comparitor;
		return comparitor(Name, a_rName);
	}
};

struct BodyData
{
	// Representation of body translation (UpperCase:world, LowerCase:local)
	double	TX, tX, btX;
	double	TY, tY, btY;
	double	TZ, tZ, btZ;

	// Representation of body rotation (UpperCase:world, LowerCase:local)
	// Quaternion
	double	QX, qX, bqX;
	double	QY, qY, bqY;
	double	QZ, qZ, bqZ;
	double	QW, qW, bqW;
	
	// Global rotation matrix
	double GlobalRotation[3][3];

	// Local rotation matrix
	double LocalRotation[3][3];
	double LocalRotationRT[3][3];
	
	// Euler rotation values (UpperCase:world, LowerCase:local)
	double EulerX, eulerX, beulerX;
	double EulerY, eulerY, beulerY;
	double EulerZ, eulerZ, beulerZ;
};

#endif